import 'dart:convert';

import 'package:sl_fast_dev/sl_fast_dev.dart';
import 'package:sl_fast_dev/src/dao/sl_container.dart';
import 'package:sl_fast_dev/src/dao/sl_decoration.dart';
import 'package:sl_fast_dev/src/dao/sl_node.dart';
import 'package:sl_fast_dev/src/kits/sl_container_factory.dart';
import 'package:sl_fast_dev/src/template/sl_templete.dart';
import 'package:sl_fast_dev/src/utils/sl_valid.dart';

class SLNodeManager {
  SLNode node;
  List<SLNode> nodes;

  Map outFiles;

  final Map docMap;
  final String path;

  SLNodeManager(this.path, {this.docMap}) {
    var nodeMap = stringToMap();

    if (nodeMap == null || nodeMap.isEmpty) return;

    node = mapToNode(nodeMap);
    nodes = nodeToList(node, isRoot: true);

    outFiles = {};

    String sl_container(String type, {String formate = 'm'}) {
      if (type == SLNodeType.RACCommand) {
        if (formate == 'h') return sl_container_RACCommand_h;
        return sl_container_RACCommand_m;
      }
      if (type == SLNodeType.UITableViewCell) {
        if (formate == 'h') return sl_container_UITableViewCell_h;
        return sl_container_UITableViewCell_m;
      }
      if (type == SLNodeType.UIView) {
        if (formate == 'h') return sl_container_UIView_h;
        return sl_container_UIView_m;
      }
      if (type == SLNodeType.UIViewController) {
        if (formate == 'h') return sl_container_UIViewController_h;
        return sl_container_UIViewController_m;
      }
      return '';
    }

    nodes.forEach((node) {
      var container = SLContainer(node);
      container.getAllHeaders().getAllProtocal();

      outFiles[container.node.cls() + '.h'] = SLContainerFactory(
        container,
        sl_container(container.node.type, formate: 'h'),
        SLNodeFor.SLNodeForUI,
        docleverMap: docMap,
      ).generate();

      outFiles[container.node.cls() + '.m'] = SLContainerFactory(
        container,
        sl_container(container.node.type),
        SLNodeFor.SLNodeForUI,
        docleverMap: docMap,
      ).generate();

      if (!SLFastDevConfig().hasVM) return;

      outFiles[container.node.viewModel() + '.h'] = SLContainerFactory(
        container,
        sl_container(SLNodeType.RACCommand, formate: 'h'),
        SLNodeFor.SLNodeForVM,
        docleverMap: docMap,
      ).generate();

      outFiles[container.node.viewModel() + '.m'] = SLContainerFactory(
        container,
        sl_container(SLNodeType.RACCommand),
        SLNodeFor.SLNodeForVM,
        docleverMap: docMap,
      ).generate();
    });

    if (!SLFastDevConfig().isCreateVC) return;

    /// 创建VC
    var container = SLContainer(node);
    container = container.getAllHeaders().getAllProtocal();

    outFiles[container.node.vc() + '.h'] = SLContainerFactory(
      container,
      sl_container(SLNodeType.UIViewController, formate: 'h'),
      SLNodeFor.SLNodeForVC,
      docleverMap: docMap,
    ).generate();

    outFiles[container.node.vc() + '.m'] = SLContainerFactory(
      container,
      sl_container(SLNodeType.UIViewController),
      SLNodeFor.SLNodeForVC,
      docleverMap: docMap,
    ).generate();
  }

  Map stringToMap() {
    return json.decode(path);
  }

  static Map defaultCell(String name) => {
        'name': '${name}Default',
        'type': SLNodeType.UITableViewCell,
        'children': [placeholder()],
      };

  static Map placeholder() => {
        'name': '++++++',
        'type': SLNodeType.SLNodeTypeNone,
      };

  bool hasCells(List nodes) {
    if (nodes == null || nodes.isEmpty) return false;

    nodes.forEach((element) {});

    for (Map node in nodes) {
      var type = SLValid.mapValueString(node, 'type');
      if (type == SLNodeType.UITableViewCell) return true;
    }

    return false;
  }

  SLNode mapToNode(Map nodeMap) {
    var name = SLValid.mapValueString(nodeMap, 'name');
    var type = SLValid.mapValueString(nodeMap, 'type');
    var text = SLValid.mapValueString(nodeMap, 'text');
    var desc = SLValid.mapValueString(nodeMap, 'desc');
    var vm = SLValid.mapValueString(nodeMap, 'vm');
    var children = SLValid.mapValueList(nodeMap, 'children');
    var decoration = getDecoration(nodeMap);

    if (type == SLNodeType.UITableView && !hasCells(children)) {
      children.add(defaultCell(name));
    }

    if (type == SLNodeType.UITableViewCell && children.isEmpty) {
      children.add(placeholder());
    }

    if (children != null && children.isNotEmpty) {
      var childrenT = <SLNode>[];

      for (var child in children) {
        childrenT.add(mapToNode(child));
      }

      return SLNode(
        name,
        type,
        children: childrenT,
        text: text,
        desc: desc,
        vm: vm,
        decoration: decoration,
      );
    }

    return SLNode(
      name,
      type,
      text: text,
      desc: desc,
      children: <SLNode>[],
      vm: vm,
      decoration: decoration,
    );
  }

  SLDecoration getDecoration(Map nodeMap) {
    var decoration = SLDecoration();

    if (nodeMap.keys.contains('decoration')) {
      Map dec = nodeMap['decoration'];

      var color = SLValid.mapValueString(dec, 'color');

      decoration = SLDecoration(color: color);
    }

    return decoration;
  }

  List<SLNode> nodeToList(SLNode node, {bool isRoot = false}) {
    var nodes = <SLNode>[];

    if (node.hasChildren()) {
      for (var child in node.children) {
        nodes.addAll(nodeToList(child));
      }
    }

    if (isRoot || node.hasChildren()) {
      node.isRoot = isRoot;
      if (!node.isContainer()) nodes.add(node);
    }

    return nodes;
  }
}
